#pragma once
#ifndef __Rendererd3d11_header_included__
#define __Rendererd3d11_header_included__

#include <Engine/IRenderer.h>
#include <Engine/Renderer/Shaders/Constants.h>
#include <Engine/Renderer/RendererStructs.h>
#include <D3DX11.h>

namespace fastbird
{
	class IObject;
	class ICamera;
	class ILight;

	class RendererD3D11 : public IRenderer
	{
	public:
		RendererD3D11();
		virtual ~RendererD3D11();
		virtual bool Init();
		virtual void Deinit();
		virtual void Clear(float r, float g, float b, float z);
		virtual void SetCamera(ICamera* pCamera);
		virtual ICamera* GetCamera() const;
		virtual void UpdateFrameConstantsBuffer();
		virtual void UpdateObjectConstantsBuffer(void* pData);
		virtual void UpdateMaterialConstantsBuffer(void* pData);
		virtual void* MapMaterialParameterBuffer();
		virtual void UnmapMaterialParameterBuffer();
		
		virtual void Present();
		virtual void SetVertexBuffer(unsigned int startSlot, unsigned int numBuffers,
			IVertexBuffer* pVertexBuffers[], unsigned int strides[], unsigned int offsets[]);
		virtual void SetIndexBuffer(IIndexBuffer* pIndexBuffer);
		virtual void SetTexture(ITexture* pTexture, BINDING_SHADER shaderType, unsigned int slot);
		virtual IVertexBuffer* CreateVertexBuffer(void* data, unsigned stride, unsigned numVertices, BUFFER_USAGE usage, BUFFER_CPU_ACCESS_FLAG accessFlag);
		virtual IIndexBuffer* CreateIndexBuffer(void* data, unsigned int numIndices, INDEXBUFFER_FORMAT format);
		virtual IShader* CreateShader(const char* filepath, IShader* pReloadingShader=0);
		virtual ITexture* CreateTexture(const Vec2I& size, int mipLevels, int arraySize);
		virtual ITexture* CreateTexture(const char* file, ITexture* pReloadingTexture=0);
		virtual ITexture* CreateTexture(void* data, int bpp, int width, int height);
		virtual IInputLayout* CreateInputLayout(INPUT_ELEMENT_DESC pDescs[], unsigned count, 
			const void* pShaderBytecodeWithInputSignature, unsigned byteLength);
		virtual void SetShader(IShader* pShader);
		virtual void SetInputLayout(IInputLayout* pInputLayout);
		virtual void SetPrimitiveTopology(PRIMITIVE_TOPOLOGY pt);
		virtual void DrawIndexed(unsigned indexCount, unsigned startIndexLocation, unsigned startVertexLocation);
		virtual void Draw(unsigned int vertexCount, unsigned int startVertexLocation);

		virtual unsigned GetWidth() const { return mWidth; }
		virtual unsigned GetHeight() const { return mHeight; }
		virtual void SetWireframe(bool enable);
		virtual bool GetWireframe() const { return mForcedWireframe; }

		virtual MapData MapVertexBuffer(IVertexBuffer* pBuffer, UINT subResource, MAP_TYPE type, MAP_FLAG flag);
		virtual void UnmapVertexBuffer(IVertexBuffer* pBuffer, unsigned int subResource);

		virtual void FindOrCreateSamplerState(ITexture* pTexture, const SAMPLER_DESC& desc);
		virtual void FindOrCreateRasterizerState(IObject* pObject, const RASTERIZER_DESC& desc);
		virtual void FindOrCreateBlendState(IObject* pObject, const BLEND_DESC& desc);
		virtual void SetRasterizerState(IRasterizerState* pRasterizerState);
		virtual void SetBlendState(IBlendState* pBlendState);

		virtual void InitFrameProfiler(float dt);
		virtual const RENDERER_FRAME_PROFILER& GetFrameProfiler() const;

	private:
		ID3D11Device*			m_pDevice; // free-threaded
		IDXGIFactory1*			m_pFactory;
		IDXGISwapChain*			m_pSwapChain;
		ID3D11DeviceContext*	m_pImmediateContext; //  not free-threaded
		ID3D11RenderTargetView* m_pRenderTargetView;
		ID3D11Texture2D*		m_pDepthStencil;
		ID3D11DepthStencilView* m_pDepthStencilView;
		ID3D11Buffer*			m_pFrameConstantsBuffer;
		ID3D11Buffer*			m_pObjectConstantsBuffer;
		ID3D11Buffer*			m_pMaterialConstantsBuffer;
		ID3D11Buffer*			m_pMaterialParametersBuffer;
		ID3D11RasterizerState*	m_pWireframeRasterizeState;
		bool					mForcedWireframe;

		DXGI_SAMPLE_DESC		mMultiSampleDesc;

		D3D_DRIVER_TYPE			mDriverType;
		D3D_FEATURE_LEVEL		mFeatureLevel;

		unsigned				mWidth;
		unsigned				mHeight;
		bool					mDepthStencilCreated;
		DXGI_FORMAT				mDepthStencilFormat;

		FRAME_CONSTANTS			mFrameConstants;
		ICamera*				mCamera;
		std::map<RASTERIZER_DESC, ID3D11RasterizerState*> mRasterizerMap;
		std::map<SAMPLER_DESC, ID3D11SamplerState*> mSamplerMap;
		std::map<BLEND_DESC, ID3D11BlendState*> mBlendMap;

		SmartPtr<ILight>		mDirectionalLight;

		RENDERER_FRAME_PROFILER		mFrameProfiler;
		
	};
}

#endif //__Rendererd3d11_header_included__